package gptma.bo.services.task;

import gptma.bo.dao.task.ImputationDao;
import gptma.bo.dao.task.TaskDao;
import gptma.bo.dao.task.TaskHistoryElementDao;
import gptma.bo.model.employee.Employee;
import gptma.bo.model.request.RequestType;
import gptma.bo.model.task.Assignment;
import gptma.bo.model.task.HistoryState;
import gptma.bo.model.task.Imputation;
import gptma.bo.model.task.Task;
import gptma.bo.model.task.TaskHistoryElement;
import gptma.bo.search.TaskSearchCriteria;
import gptma.bo.util.ModelConstants;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

import javax.ejb.Stateless;
import javax.inject.Inject;

@Stateless
public class TaskServicesImpl implements TaskServices {

	@Inject
	private TaskDao taskDao;

	@Inject
	private ImputationDao imputationDao;

	@Inject
	private TaskHistoryElementDao taskHistoryElementDao;

	@Override
	public List<Task> findAll() {
		return taskDao.findAll();
	}

	@Override
	public List<Task> findNonAssigned() {
		return taskDao.findNonAssigned();
	}

	@Override
	public List<Task> findNonAttached() {
		return taskDao.findNonAttached();
	}

	@Override
	public List<Assignment> findAssignments(Task task, Employee employee) {
		List<Assignment> ret = new ArrayList<Assignment>();
		Set<Assignment> all = task.getAssignments();
		if (all != null) {
			for (Assignment assignment : all) {
				if (assignment.getEmployee().equals(employee)) {
					ret.add(assignment);
				}
			}
		}

		return ret;
	}

	@Override
	public List<Task> findByCriteria(TaskSearchCriteria criteria) {
		return taskDao.findByCriteria(criteria);
	}

	@Override
	public float findConsolidatedCharge(Task task) {
		float ret = 0;

		List<Imputation> imputs = imputationDao.findImputations(task);
		if (imputs != null) {
			for (Imputation imputation : imputs) {
				ret += imputation.getCharge();
			}
		}

		return ret;
	}

	@Override
	public float findConsolidatedCharge(Task task, Date date) {
		return taskDao.findConsolidatedCharge(task, date);
	}

	@Override
	public boolean findExistingCode(String code) {
		return taskDao.findExistingCode(code);
	}

	@Override
	public List<Imputation> findImputation(Task task) {
		return imputationDao.findImputations(task);
	}

	@Override
	public int findMaxPriority() {
		return taskDao.findMaxPriority();
	}

	@Override
	public List<String> getAllStatus() {
		List<String> ret = new ArrayList<String>();

		HistoryState[] tab = HistoryState.values();
		for (HistoryState historyState : tab) {
			ret.add(historyState.getLabel());
		}

		return ret;
	}

	@Override
	public List<String> getTaskTypeForRequest(RequestType type) {
		List<String> ret = new ArrayList<String>();

		switch (type) {
		case DE:
			ret.add(ModelConstants.FAI_TASK);
			ret.add(ModelConstants.IAA_TASK);
			ret.add(ModelConstants.IAU_TASK);
			ret.add(ModelConstants.ICS_TASK);
			ret.add(ModelConstants.INTEGRATION_TASK);
			ret.add(ModelConstants.LINEA_TASK);
			ret.add(ModelConstants.LINEALC_TASK);
			ret.add(ModelConstants.LINEANOT_TASK);
			ret.add(ModelConstants.LINEAIHM_TASK);
			ret.add(ModelConstants.SAFFIRE_TASK);
			ret.add(ModelConstants.SKIPPER_TASK);
			ret.add(ModelConstants.IWS_FAI_TASK);
			break;

		case RA:
			ret.add(ModelConstants.AR_TASK);
			break;

		default:
			break;
		}

		return ret;
	}

	@Override
	public List<Float> getAllowedCharges() {
		List<Float> ret = new ArrayList<Float>();
		ret.add(Float.valueOf((float) 0.25));
		ret.add(Float.valueOf((float) 0.50));
		ret.add(Float.valueOf((float) 0.75));
		ret.add(Float.valueOf(1));

		return ret;
	}

	@Override
	public float getCurrentEtc(Task task) {
		float ret = 0;

		Imputation last = imputationDao.findLastImputation(task);
		if (last != null) {
			ret = last.getEtc();
		} else {
			ret = task.getSoldCharge();
		}

		return ret;
	}

	@Override
	public void saveTask(Task task) {

		String currentState = task.getCurrentState();
		TaskHistoryElement oldState = taskDao.findCurrentState(task);
		TaskHistoryElement newState = null;
		if (oldState == null
				|| !oldState.getState().getLabel().equals(currentState)) {
			newState = new TaskHistoryElement();
			newState.setDate(new Date());
			newState.setState(HistoryState.getFromLabel(currentState));
			newState.setTask(task);
		}

		taskDao.save(task);
		if (newState != null) {
			taskHistoryElementDao.save(newState);
		}
	}

	@Override
	public void updateTaskAndDependencies(Task task,
			TaskHistoryElement historyElement) {
		taskDao.save(task);
		taskHistoryElementDao.save(historyElement);
	}

}
